#ifndef USERDB_H
#define USERDB_H

#include <unistd.h>
#include <sys/types.h>
#include <stddef.h>
#include <pthread.h>
#include "clib/data_struct.h"

/* 本地登录用户列表 */
struct local_userdb
{
	uid_t uid;
	gid_t gid;
	char login_name[1024];	//针对中文,统一使用utf8的编码
	int sockfd;
	struct list_head i_list;
	pid_t pid;
};
typedef struct lu_desc	//为了以后扩展可用, 本地登录用户列表描述符
{
	struct list_head head;
	pthread_rwlock_t lu_lock;
}lu_desc_t;

/* 
 * 以特定条件搜索一个用户, desc为lu_desc_t 型指针
 * member为进行比较的分量, value为要比较的值, 且value必须为一个指针
 * size为一次要比较的字节数
 */
#define local_user_search(desc, member, value, size) ({\
	struct list_head *ptr = NULL; \
	struct local_userdb *p = NULL, *q = NULL; \
	void *tmp = NULL; \
	pthread_rwlock_rdlock(&((desc)->lu_lock)); \
	list_for_each(ptr, &((desc)->head)) { \
		p = list_entry(ptr, struct local_userdb, i_list); \
		tmp = p; \
		tmp += offsetof(struct local_userdb, member); \
		if (!memcmp(tmp, (value), (size))) { \
			q = p; \
			break; \
		} \
	} \
	pthread_rwlock_unlock(&((desc)->lu_lock)); \
	q; \
})

/* 用户结构的获得字段值
 * desc为用户列表描述符
 * user为用户节点指针
 * member为要得到的字段值的字段名
 * 返回一个由malloc分配的空间，其中包含需要的值
 * 由该宏获得的字段值应由local_user_free_item释放
 */
#define local_user_get_item(desc, user, member) ({ \
	pthread_rwlock_rdlock(&((desc)->lu_lock));\
	void *p = (void *)(user);\
	typeof(((struct local_userdb *)0)->member) *item = NULL;\
	int size;\
	p += offsetof(struct local_userdb, member); \
	size = sizeof(typeof(((struct local_userdb *)0)->member));\
	item = malloc(size);\
	memcpy(item, p, size);\
	pthread_rwlock_unlock(&((desc)->lu_lock));\
	item;\
})

#define local_user_free_item(p) free((p))

/* 在线用户列表 */
struct online_userdb
{
	uint32_t serial;
	char *user_name;
	char *host;
	char *group;
	char *nickname;
	char *ipaddr;
	struct list_head i_list;
	//unsigned long cap;
};
typedef struct ou_desc	//为了以后扩展可用
{
	struct list_head *head;
}ou_desc_t;

struct local_userdb *create_local_user(uid_t uid, gid_t gid, const char *login_name, int sockfd, pid_t pid);
void destroy_local_user(struct local_userdb *user);
lu_desc_t *local_user_open(void);
void local_user_add(lu_desc_t *lu_d, struct local_userdb *user);
void local_user_del(lu_desc_t *lu_d, struct local_userdb *user);
void local_user_close(lu_desc_t *desc);
#endif
